一致性hash和redis中hash槽的区别

您所在的位置:网站首页 redis 集群 一致性 一致性hash和redis中hash槽的区别

一致性hash和redis中hash槽的区别

2024-07-11 01:56| 来源: 网络整理| 查看: 265

一致性hash主要用于分布式系统中,用于解决数据选择节点存储、选择节点访问、增删节点后数据的迁移和重分布问题。redis集群并没有使用一致性hash,而是使用了hash槽来解决数据分配的问题。

一致性hash:

它是一个0-2^32次方的圆,主要操作步骤:将每一个服务节点进行hash(如ip),让其落在这个闭合的圆环上;当我们进行数据存储或访问时,计算key的hash值,让其也落在这个闭合圆环之中;那么它顺时针找到的第一个服务节点就是处理key的节点

当添加节点时,例如再节点2和4之间添加了一个节点5,那么就有可能伴随数据的重分配,图中黄色区域的数据被分配到了节点5之上

当删除节点时,那么它的数据就会被分配到它顺时针寻找到的下一个节点之上。以下图为例节点2被删除,2的数据被分配到了4,那么就有可能出现一个问题,4的访问量或内存使用率就会瞬间增高,如果2之上有热点数据,就有可能将4直接打挂,这样就会顺延再将数据转移到3,从而导致所有节点循环崩溃。

同时当集群中节点过少时还有可能出现数据倾斜,大量的数据都被分配到了同一个节点上,导致单一节点内存使用率和qps都很高,分布式服务的负载不平衡。如下图所示,从A顺时针到B明显比B顺时针到A所占的区域小,那么数据被分配到A的概率就会比B大。

为了解决循环崩溃现象和数据倾斜现象,提出了虚拟节点的概念。就是将真实节点计算多个哈希形成多个虚拟节点并放置到哈希环上,定位算法不变,只是多了一步虚拟节点到真实节点映射的过程。如下图所示每个节点都映射出了两个虚拟节点,当节点1挂掉以后,它的数据并没有全部转移到同一个节点,而是被分配到了v301和v200,即节点2和3之上;此外由于加入了虚拟节点数据倾斜的问题也得到了解决。

redis 使用数据分片的hash槽来应对数据存储和读取。redis集群共有2^14次方16384个hash槽,当操作数据时,使用CRC16算法计算key的hash值,然后与16384取模从而确定该数据是属于哪一个slot槽的。redis集群中,每个服务节点都被分配一段hash槽,只要确定了数据属于哪一个槽,就可以确定该数据是在哪一个节点之上。槽是可以迁移的,master节点的slave节点不分配槽,只拥有读权限即使用权。但是注意在代码中redis cluster执行读写操作的都是master节点,并不是你想 的读是从节点,写是主节点(不过应该可以进行设置,从节点也提供读的能力,因为MT的Squirrel从节点可以提供读能力)。第一次新建redis cluster时,16384个槽是被master节点均匀分布的。当新增或删除master节点时,需要对槽进行重分配,而不是直接对数据进行分配。对于hash槽的转移和分配,redis不会自动进行,需要人工辅助。

一致性hash和redis hash槽的区别

1. redis hash槽并不是闭合的,它一共有16384个槽,使用CRC16算法计算key的hash值,与16384取模,确定数据在哪个槽中,从而找到所属的redis节点;一致性hash表示一个0到2^32的圆环,对数据计算hash后落到该圆环中,顺时针第一个节点为其所属服务。

2.一致性hash是通过虚拟节点去避免服务节点宕机后数据转移造成的服务访问量激增、内存占用率过高、数据倾斜等问题,保证数据完整性和集群可用性的;而hash集群是使用主从节点的形式,主节点提供读写服务,从节点进行数据同步备份,当主节点出现故障后,从节点继续提供服务。

二、redis集群中数据迁移

当向集群中添加节点后,新添加的节点中是没有分配槽的,假设我们新在集群中添加了节点D,那么可以将现有节点(A、B、C)的slot分配给新节点。例如从A分配slot8至D,那么在槽迁移的中间状态下slot8在A表现为MIGRATING、在D表现为IMPORTING。

当槽迁移的过程中,发生了key属于该槽的请求即当客户端请求的key处于在正在迁移的某个slot时,因为此时节点的映射关系(即槽与节点的映射)还没有改变,客户端依然认为slot8是属于A的,但是其中的一些key所对应的数据可能已经被转移到了D,对于A来说会有如下几种情况:

(1)key还在A,那么进行处理后返回

(2)key不在A了,返回ASK,让其发送ASKING命令到目标节点即D,然后进行请求

(3)如果命令包括了多个key,如果这些key都存在则进行操作后返回;如果都不存在返回客户端ASK;如果部分存在,则返回客户端TRYAGAIN,通知客户端稍后重试,这样当所有的key都迁移完成后再请求就会返回ASK

如果请求了目标节点的IMPORTING状态的slot,会出现以下几种情况

(1)如果是正常的请求则会发送MOVED命令,此时说明节点映射出错了,迁移还没有完成,被slot还属于源节点,会刷新映射

(2)如果是ASKING命令则会被执行,key存在,执行操作后返回;key不存在,则会被新建

键空间迁移

在槽迁移的前提下,还会进行键迁移,即将节点A中槽8对应键空间迁移至节点D。执行migrate命令,分为三步完成该过程,即dump(A)、restore(D)、del(A)

完成之后会将处于migrating和importing状态的槽置为正常状态,同时会刷新槽与节点的映射关系

在redis代码表示节点node的结构体ClusterNode中,存在一个char类型的slots数组和一个int型numSlots,数组长度是2048,表示一个二进制位数组,包含16384个二进制位,每一位默认为0,如果一个slot属于该节点,那么它在数组中对应下标所在的二进制位就会变成1;numslots表示该节点拥有多少个槽。

而槽的分配信息存储在clusterState结构体的clusterNode类型的数组中,它的长度为16384,即我们通过CRC16算法得出key的hash值,并对16384取模后使用该值对应的slot是哪一个,获取数组对应下标的元素,它就是该槽所属的redis节点。

redis集器并不会使用代理,当一个操作请求来到了节点a,但是经过计算发现key对应的槽不在a上,那么此时a会执行move命令将它转发到正确的节点上

Redis Cluster 分区实现原理 - _1900 - 博客园

redis:ASK错误和MOVED错误区别_machitaoX的博客-CSDN博客_ask错误

对话张冬洪 | 全面解读NoSQL数据库Redis的核心技术与应用实践_数据和云的博客-CSDN博客



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3